/*
 *Copyright (c) 2024 Black Sesame Technologies
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
*/

#ifndef __CAN_OUTPUT_H__
#define __CAN_OUTPUT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "../hscg_flexcan/Hscg_SwFifo.h"
#include "VCan_Types.h"
#include "VCan_Command.h"
#include "hscg_firmware.h"
#include "mcu_id.h"

#define CAN_TX_ERR_OK 0
#define CAN_TX_ERR_PARA -1
#define CAN_TX_ERR_NOMEM -2
#define CAN_TX_ERR_QUEUE_FULL -3
#define CAN_TX_ERR_QUEUE_EMPTY -4
#define CAN_TX_ERR_NOMB -5
#define CAN_TX_ERR_INTERNAL -6

#define CAN_BUILD_CS_ATTR(_dlc, _rtr, _ide, _srr, _esi, _brs, _edl)         \
(((_dlc) << FLEXCAN_IP_CS_DLC_SHIFT) |((_rtr) << FLEXCAN_IP_CS_RTR_SHIFT)   \
| ((_ide) << FLEXCAN_IP_CS_IDE_SHIFT) | ((_srr) << FLEXCAN_IP_CS_SRR_SHIFT) \
| ((_esi) << FLEXCAN_IP_CS_ESI_SHIFT) | ((_brs) << FLEXCAN_IP_CS_BRS_SHIFT) \
| ((_brs) << FLEXCAN_IP_CS_BRS_SHIFT) | ((_edl) << FLEXCAN_IP_CS_EDL_SHIFT))


uint8 utils_canfd_datalen_to_dlc(uint8 datalen);
uint8 utils_dlc_to_canfd_datalen(uint8 DLC);
uint32
util_compute_len_between_two_ring_ptr(uint8* first, uint8* second, size_t size, uint8* ring_start, uint8* ring_end);
typedef enum
{
    DCACHE_INVAL_RANGE	= 1,
    DCACHE_CLEAN_INVAL_RANGE =2
}CacheOpsType;
/* CCSIDR */
#define CCSIDR_LINE_SIZE_OFFSET		0
#define CCSIDR_LINE_SIZE_MASK		0x7
#define CCSIDR_ASSOCIATIVITY_OFFSET	3
#define CCSIDR_ASSOCIATIVITY_MASK	(0x3FF << 3)
#define CCSIDR_NUM_SETS_OFFSET		13
#define CCSIDR_NUM_SETS_MASK		(0x7FFF << 13)
void DcacheMaintRange(uint32 start, uint32 stop, CacheOpsType range_op);

void can_txque_init(void);
bool can_txque_is_empty(uint32 txque_idx);
sint32 can_txque_dequeue(uint32 txque_idx, void **tx_msg);
sint32 can_txque_enqueue(uint32 txque_idx, void *tx_msg);
sint32 can_output_queue_send(uint32 can_bus, uint32 msg_id, uint32 cs, const uint8 *data, uint32 dataLen);

sint8 can_tx_mb_idx_query(uint32 src_ctrl_idx, uint32 src_filter_id, uint32 dest_ctrl_idx);
sint32 can_tx_mb_map_set(uint32 src_ctrl_idx, uint32 src_filter_id, uint32 dest_ctrl_idx);
void can_tx_mb_map_init(void);

void can_output_init(void);
void can_output_run(void);
void can_que_mb_addr_init(uint32 controller_id);
int utils_get_ipc_cpu_id_by_destination_id(uint8 des_id);
int utils_get_destination_id_by_ipc_cpu_id(uint8 pid);
int utils_get_consumer_mask_by_destination_id(uint8 des_id);
int utils_get_destination_id_by_consumer_mask(uint8 consumer_mask);
#ifdef __cplusplus
}
#endif

#endif